home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Technotools
/
Technotools (Chestnut CD-ROM)(1993).ISO
/
lang_c
/
cug189
/
fcomp.c
< prev
next >
Wrap
Text File
|
1985-08-21
|
4KB
|
211 lines
/* fcomp.c: file comparator that beats DIFF! */
#include <stdio.h>
#define MAXLINES 1000
#define ORIGIN MAXLINES
#define INSERT 1
#define DELETE 2
struct edit {
struct edit *link;
int op;
int line1;
int line2;
};
char *A[MAXLINES], *B[MAXLINES];
main(argc,argv)
int argc;
char *argv[];
{
int max_d,
m,
n,
lower,
upper,
d,
k,
row,
col;
int last_d[2*MAXLINES+1];
struct edit *script[2*MAXLINES+1];
struct edit *new;
char *malloc();
if (argc > 1 && argv[1][0] == '-')
{
max_d = atoi(&argv[1][1]);
++argv;
--argc;
}
else
max_d = 2*MAXLINES;
if(argc != 3)
fatal("diff requires two file names.");
m = in_file(argv[1],A);
n = in_file(argv[2],B);
for (row=0 ; row<m && row < n && strcmp(A[row],B[row]) == 0 ; ++row)
;
last_d[ORIGIN] = row;
script[ORIGIN] = NULL;
lower = (row == m) ? ORIGIN + 1 : ORIGIN - 1;
upper = (row == n) ? ORIGIN - 1 : ORIGIN + 1;
if (lower > upper)
{
puts("The files are identical.");
exit();
}
for (d = 1 ; d <= max_d ; ++d)
{
for ( k = lower ; k <= upper ; k +=2)
{
new = (struct edit *) malloc(sizeof(struct edit));
if (new == NULL)
exceed(d);
if (k == ORIGIN-d || k != ORIGIN+d && last_d[k+1] >= last_d[k-1])
{
row = last_d[k+1]+1;
new->link = script[k+1];
new->op = DELETE;
}
else
{
row = last_d[k-1];
new->link = script[k-1];
new->op = INSERT;
}
new->line1 = row;
new->line2 = col = row + k - ORIGIN;
script[k] = new;
while(row < m && col < n && strcmp(A[row],B[col]) == 0)
{
++row;
++col;
}
last_d[k] = row;
if (row == m && col == n)
{
put_scr(script[k]);
exit();
}
if (row == m)
lower = k+2;
if (col == n)
upper = k-2;
}
--lower;
++upper;
}
exceed(d);
}
in_file(filename,P)
char *filename, *P[];
{
char buf[100], *malloc(), *fgets(), *save, *b;
FILE *fp, *fopen();
int lines = 0;
if ((fp = fopen(filename,"r")) == NULL)
{
fprintf(stderr, "Cannot open file %s.\n",filename);
exit();
}
while(fgets(buf,100,fp) != NULL)
{
if (lines >= MAXLINES)
fatal("File is to large for diff.");
if ((save = malloc(strlen(buf)+1)) == NULL)
fatal("Not enough room to save the files.");
P[lines++] = save;
for (b = buf ; *save++ = *b++ ; )
;
}
fclose(fp);
return(lines);
}
put_scr(start)
struct edit *start;
{
struct edit *ep, *behind, *ahead, *a, *b;
int change;
ahead = start;
ep = NULL;
while (ahead != NULL)
{
behind = ep;
ep = ahead;
ahead = ahead->link;
ep->link = behind;
}
while( ep != NULL)
{
b = ep;
if (ep->op == INSERT)
printf("Inserted after line %d:\n",ep->line1);
else
{
do
{
a = b;
b = b->link;
} while (b!=NULL && b->op == DELETE && b->line1 == a->line1+1);
change = (b!=NULL && b->op == INSERT && b->line1 == a->line1);
if (change)
printf("\nChanged ");
else
printf("\nDeleted ");
if (a == ep)
printf("line %d\n",ep->line1);
else
printf("lines %d-%d:\n",ep->line1,a->line1);
do
{
printf(" %s",A[ep->line1-1]);
ep = ep->link;
} while (ep != b);
if (!change)
continue;
printf("To:\n");
}
do
{
printf(" %s",B[ep->line2-1]);
ep = ep->link;
} while (ep != NULL && ep->op == INSERT && ep->line1 == b->line1);
}
}
fatal(msg)
char *msg;
{
fprintf(stderr,"%s\n",msg);
exit();
}
exceed(d)
int d;
{
fprintf(stderr,"The files differ in at least %d lines. \n",d);
exit();
}
y d$ SUBST C